import importlib.util
import os
import re


def import_from_abspath(abs_path: str):
    """
    功能：根据.py文件的绝对路径安全导入模块。
    特点：支持windows和linux的绝对路径导入python文件；
    要求：windows的绝对路径双引号的前面必须加上r；
    调用：
    module1=import_from_abspath(abs_path)
    module1.func1()
    """
    try:
        abs_path = abs_path.encode('utf-8').decode('unicode_escape')
    except (UnicodeDecodeError, UnicodeError):
        pass
    abs_path = abs_path.replace('\\', '/')
    if not os.path.isabs(abs_path):
        raise ValueError("必须传入绝对路径")
    if not os.path.isfile(abs_path):
        raise FileNotFoundError(abs_path)
    module_name = os.path.splitext(os.path.basename(abs_path))[0]
    spec = importlib.util.spec_from_file_location(module_name, abs_path)
    if spec is None or spec.loader is None:
        raise ImportError(f"无法加载 {abs_path}")
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


import os
import importlib.util
import sys
from typing import Any

def import_from_relpath_same_folder(file_name: str, module_name: str = None) -> Any:
    """
    从当前目录的相对路径导入模块
    
    Args:
        file_name: 要导入的文件名（包括扩展名）
        module_name: 可选的自定义模块名，默认为文件名（不含扩展名）
    
    Returns:
        导入的模块对象
        
    Raises:
        FileNotFoundError: 当指定文件不存在时
        ImportError: 当导入过程中出现错误时
    """
    # 获取当前文件所在目录
    current_dir = os.path.dirname(os.path.abspath(__file__))
    file_path = os.path.join(current_dir, file_name)
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"文件不存在: {file_path}")
    
    # 如果没有提供模块名，使用文件名（不含扩展名）
    if module_name is None:
        module_name = os.path.splitext(file_name)[0]
    
    # 如果模块已经在sys.modules中，直接返回
    if module_name in sys.modules:
        return sys.modules[module_name]
    
    try:
        # 创建模块规范并加载模块
        spec = importlib.util.spec_from_file_location(module_name, file_path)
        if spec is None:
            raise ImportError(f"无法为文件创建模块规范: {file_path}")
        
        module = importlib.util.module_from_spec(spec)
        
        # 将模块添加到sys.modules中以便后续导入
        sys.modules[module_name] = module
        
        # 执行模块代码
        spec.loader.exec_module(module)
        
        return module
        
    except Exception as e:
        # 如果导入失败，从sys.modules中移除模块
        if module_name in sys.modules:
            del sys.modules[module_name]
        raise ImportError(f"导入模块失败: {file_path}") from e

# 使用示例
if __name__ == "__main__":
    other_module = import_from_relpath_same_folder("str_valid.py")
    print(other_module.is_valid_text("abc"))
    print(f"成功导入模块: {other_module.__name__}")
